#ifndef UI_H
#define UI_H

#include <QtGui>
#include <QVTKWidget.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/point_picking_event.h>
#include <pcl/visualization/interactor.h>
#include <vtkSmartPointer.h>
#include "pcqc.h"
/*!
 \file ui.h This class defines the application's interface.
 \author Sqizzato Stefano
 \author Maroso Alessandro

*/

/*!
 \brief This class defines the application's interface. All classes that contain signals or slots must mention Q_OBJECT at the top of their declaration. They must also derive (directly or indirectly) from QObject.
 \author Sqizzato Stefano
 \author Maroso Alessandro

*/
class Ui : public QMainWindow
{
    Q_OBJECT

public:

// INIT
    /*!
     \brief Constructor, also inits the pointer to the pcqc object external to the interface

     \param[in] pcqc
    */
    Ui(Pcqc *pcqc);

    /*!
     \brief Destructor is not needed for the gui elements because everything is parented in the QObjects tree.
            The only thing to delete is the viewer, the motor is allocated in the stack and manages its memory internally.
            They are deleted when the parent (main window->mainWidget) is deleted.

    */
    ~Ui();

// SETTERS
    /*!
     \brief To set another motor if we want the ui work with different pcqc instances.

     \param[in] pcqc
    */
    void setMotor(Pcqc *pcqc);

// GETTERS
    /*!
     \brief Returns a pointer to the pcqc object.

     \return Pcqc the pcqc object.
    */
    Pcqc* getMotor();
    /*!
     \brief Returns the main window's visualizer.

     \return pcl::visualization::PCLVisualizer the main window's visualizer.
    */
    pcl::visualization::PCLVisualizer* getViewer();
    /*!
     \brief Returns the dialog's visualizer.

     \return pcl::visualization::PCLVisualizer the dialog's visualizer.
    */
    pcl::visualization::PCLVisualizer* getDialogViewer();
    /*!
     \brief Returns the main window's widget that holds the visualizer's renderer

     \return QVTKWidget the main window's widget that holds the visualizer's renderer
    */
    QVTKWidget* getViewerWidget();
    /*!
     \brief Returns the dialog window's widget

     \return QDialog the dialog window's widget
    */
    QDialog* getComponentDialog();

private slots:
    /*!
     \brief about menu.

    */
    void about();
    /*!
     \brief about menu PLC entry.

    */
    void aboutPCL();
    /*!
     \brief Loads a file browser to load a cloud.

    */
    void browseLoadTarget();
    /*!
     \brief Opens a dialog for the component definition.

    */
    void openComponentDialog();
    /*!
     \brief Registers a point pick callback to the dialog point cloud viewer.
     \deprecated not in use anymore.

    */
    void setComponentDialogCallback();
    /*!
     \brief  Resets the point pick callback to the dialog point cloud viewer.
     \deprecated not in use anymore.

    */
    void resetComponentDialogCallback();
    /*!
     \brief Set the color segmentation threshold for the component definition.

    */
    void setColorThreshold();
    /*!
     \brief Set the cluster segmentation threshold for the component definition.

    */
    void setClusterThreshold();
    /*!
     \brief Set the shape matching shape's ckin thickness the component matching.

    */
    void setSkinThickness();
    /*!
     \brief Set the score distance threshold described in registration.h

    */
    void setScoreDistanceThreshold();
    /*!
     \brief Visualize only the last defined component in the visualizer

    */
    void segmentComponent();
    /*!
     \brief Saves the last defined component.

    */
    void saveComponent();
    /*!
     \brief Delete the component selected  in the components list.

    */
    void deleteComponent();
    /*!
     \brief Performs an automatic component detection

    */
    void autoComponentDetection();
    /*!
     \brief Opens a dialog for the checks definition.

    */
    void openCheckDialog();
    /*!
     \brief Saves the last defined check.

    */
    void saveCheck();
    /*!
     \brief Save the defined check for all the components present in the component list.

    */
    void saveCheckAll();
    /*!
     \brief Delete the check selected in the checks list.

    */
    void deleteCheck();

    /*!
     \brief Loads a file browser to load all the clouds in a folder.

    */
    void browseSourceFolder();

    /*!
     \brief Loads the source cloud with the specified filename.

    */
    void loadSourceCloud(QString fileName);

    /*!
     \brief Executes the application's logic.

    */
    void start();
    /*!
     \brief Show target cloud in the visulizer.

    */
    void showTarget();
    /*!
     \brief Show source cloud in the visualizer.

    */
    void showSource();
    /*!
     \brief Show registered cloud in the visualizer.

    */
    void showRegistered();
    /*!
     \brief Show difference cloud in the visualizer.

    */
    void showDifference();
    /*!
     \brief Show the target component clicked in the components list in the visualizer.

     \param[in] item The item clicked in the components list.
    */
    void showTargetComponent(QListWidgetItem *item);
    /*!
     \brief Show the source component selected in the combo box.

    */
    void showSourceComponent();
    /*!
     \brief Clear all the clouds from the visualizer.

    */
    void clearAll();




private:
// UI FUNCTIONS
    /*!
     \brief Setup the menu bar of the interface.

    */
    void setupMenuBar();
    /*!
     \brief Setup the status bar of the interface.

    */
    void setupStatusBar();
    /*!
     \brief Setup the "load reference cloud" box of the interface.

    */
    void setupLoadTBox();
    /*!
     \brief Setup the "define component" box of the interface.

    */
    void setupComponentsBox();
    /*!
     \brief Setup the "define checks" box of the interface.

    */
    void setupChecksBox();
    /*!
     \brief Setup the "load source cloud" box of the interface.

    */
    void setupLoadSBox();
    /*!
     \brief Setup the PCL visualizer of the main interface.

    */
    void setupVisualizer();
    /*!
     \brief Setup the "results" box of the interface.

    */
    void setupResultsBox();
    /*!
     \brief Setup the "visualizer's commands" box of the interface.

    */
    void setupVisualizerCommandsBox();
    /*!
     \brief Setup the main layout of the interface.

    */
    void setupMainLayout();
    /*!
     \brief Point pick callback function to collect user's clicks on the visualizer.

     \param[in] event The click on a point event.
     \param[in] cookie A pointer to the Ui object to interact with it at every click.
    */
    static void pointPickCallback(const pcl::visualization::PointPickingEvent& event, void* cookie);
    /*!
     \brief Point pick callback function to collect user's clicks on the component's definition visualizer.

     \param[in] event The click on a point event.
     \param[in] cookie A pointer to the Ui object to interact with it at every click.
    */
    static void pointPickCallbackSelectComponent(const pcl::visualization::PointPickingEvent& event, void* cookie);
    /*!
     \brief Transforms a QColor to a style sheet.

     \param[in] color The input color to transform.
     \return QString The string representing the style sheet.
    */
    static QString colorToStyleSheet(QColor *color);
    /*!
     \brief  Setup the source component's combo box of the interface.

    */
    void setupSourceComboBox();
    /*!
     \brief Setup the input check's combo box with all the components defined.

     \param[in] cb The combo box to be set up.
    */
    void setupChecksComboBox(QComboBox *cb);

// Motor object
    Pcqc *motor; /*!< The object where all the logic is contained. */

// Main UI

    QLineEdit *pathTField; /*!< Editable line containing the path to the reference cloud. */
    QLineEdit *pathSourceFolderField; /*!< Editable line containing the path to the source clouds' folder. */
    QStringList *filesNamesList; /*!< List of strings containing the name of the source clouds files. */
    QComboBox *sourceCloudsComboBox; /*!< Combo box containing the source clouds in the selected folder. */
    QListWidget *componentsList; /*!< List of all the components. */
    QListWidget *checksList; /*!< List of all the checks. */
    QTextEdit *resultsList; /*!< Text field for the output of the program. */
    QPushButton *showSComponentButton; /*!<  Button to show the a source component. */
    QComboBox *sourceComponentsList; /*!< Combo box of the components. */
    QVTKWidget *qvtkVisualizer; /*!< Widget containing the pcl visualizer to wrap it in a QWidget. */
    pcl::visualization::PCLVisualizer *viewer; /*!< The pcl visualizer. */
    bool isCameraCentered; /*!< Check if the camera is already centered to the current cloud area. */
    QGroupBox* loadTBox; /*!<  The box for loading the target cloud. */
    QGroupBox *componentsBox; /*!< The box for defining components. */
    QGroupBox *checksBox; /*!< The box for defining checks. */
    QGroupBox *loadSBox; /*!< The box for loading source cloud. */
    QGroupBox *resultsBox; /*!< The box for the results. */
    QGroupBox *visualizerCommandsBox; /*!< The box for the visualizer's commands. */

// Dialog UIs
    QDialog *addComponentDialog; /*!< Dialog window for adding a component */
    boost::signals2::connection componentCallbackConnection;  /*!< Callback connection to the "add component dialog" */
    pcl::visualization::PCLVisualizer *dialogViewer; /*!< Visualizer for the "add component dialog" */
    QDialog *addCheckDialog; /*!< dialog window for adding a check */

};

#endif // UI_H
